using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;

namespace Gko.Utils
{
	/// <summary>
	/// <see cref="T:System.Security.SecureString"/> extensions
	/// </summary>
	public static class SecureStringExtensions
	{
		/// <summary>
		/// Converts secure string to the string.
		/// </summary>
		/// <param name="secureString">The secure string to convert.</param>
		/// <returns>String.</returns>
		/// <exception cref="System.ArgumentNullException">secureString is <c>null</c></exception>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unsecure")]
		public static string ToUnsecureString(this SecureString secureString)
		{
			if(secureString.IsNull()) {
				throw new ArgumentNullException("secureString");
			}
			using (var mem = secureString.ToGlobalAllocUnicode().ToMemoryBlock(secureString.Length * 2, Marshal.ZeroFreeGlobalAllocUnicode)) {
				return mem.ToIntPtr().ToUnicodeString(mem.Size / 2);
			}
		}

		/// <summary>
		/// Copies the contents of a managed <see cref="T:System.Security.SecureString"/> into unmanaged memory.
		/// </summary>
		/// <param name="secureString">The secure string.</param>
		/// <returns>The address, in unmanaged memory, to where the s parameter was copied, or 0 if a null System.Security.SecureString was supplied</returns>
		/// <exception cref="System.ArgumentNullException">secureString is <c>null</c></exception>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Alloc")]
		public static IntPtr ToGlobalAllocUnicode(this SecureString secureString)
		{
			if (secureString.IsNull()) {
				throw new ArgumentNullException("secureString");
			}
			return Marshal.SecureStringToGlobalAllocUnicode(secureString);
		}
	}
}